/**
 * 
 */
package com.jlp.agents.memory;

import java.lang.instrument.Instrumentation;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import com.jlp.agents.agent.client.AgentSender;
import com.jlp.agents.agent.client.IMessage;
import com.jlp.agents.agent.client.MessageBuilder;

/**
 * @author Anis
 * 
 */
public class MemoryAgentCommand {
	public static void premain(String agentArguments, Instrumentation instrumentation){
		run(instrumentation);
	}

	public static void run(final Instrumentation inst, String... args) {
		Timer timer = new Timer("HeapCounter");
		
		TimerTask task = new TimerTask() {
			public void run() {
				try {

					ThreadMXBean tb = ManagementFactory.getThreadMXBean();
					int threadCount = tb
							.getThreadCount();
					

					//memory
					MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
					MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
					long committed = heapMemoryUsage.getCommitted();
					long init = heapMemoryUsage.getInit();
					long max = heapMemoryUsage.getMax();
					long used = heapMemoryUsage.getUsed();
					long currentTimeMillis = System.currentTimeMillis();
					MessageBuilder messageBuilder = new MessageBuilder(currentTimeMillis);
					messageBuilder.setGroupName("heap");
					messageBuilder.putCounter("committed", committed);
					messageBuilder.putCounter("max", max);
					messageBuilder.putCounter("init", init);
					messageBuilder.putCounter("used", used);
					IMessage message = messageBuilder.getMessage();
					AgentSender.send(message);
					
					//thread
					messageBuilder = new MessageBuilder(currentTimeMillis);					
					messageBuilder.putCounter("thread|threadCount", threadCount);
					message = messageBuilder.getMessage();
					AgentSender.send(message);
					
					// classloading
					ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
					int loadedClassCount  = classLoadingMXBean.getLoadedClassCount();
					long totalLoadedClassCount = classLoadingMXBean.getTotalLoadedClassCount();
					long unloadedClassCount = classLoadingMXBean.getUnloadedClassCount();
					messageBuilder = new MessageBuilder(currentTimeMillis);
					messageBuilder.setGroupName("classloading");
					messageBuilder.putCounter("loadedClassCount", loadedClassCount);
					messageBuilder.putCounter("totalLoadedClassCount", totalLoadedClassCount);
					messageBuilder.putCounter("unloadedClassCount", unloadedClassCount);
					message = messageBuilder.getMessage();
					AgentSender.send(message);
					
					//GC
					List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans();
					messageBuilder = new MessageBuilder(currentTimeMillis);
					messageBuilder.setGroupName("GC");
					for (GarbageCollectorMXBean gc : garbageCollectorMXBeans) {
						String name = gc.getName();
						long collectionCount = gc.getCollectionCount();
						long collectionTime = gc.getCollectionTime();
						messageBuilder.putCounter(name+"|collectionCount", collectionCount);
						messageBuilder.putCounter(name+"|collectionTime", collectionTime);
						
					}
					message = messageBuilder.getMessage();
					AgentSender.send(message);
					
					
				} catch (Throwable t) {
					System.err.println("Exception in agent: " + t);
				}
			}

			@Override
			protected void finalize() throws Throwable {
				super.finalize();
				System.out.println(".finalize()");
			}
			
		};
		timer.schedule(task, 0,2000);
	}
}
